home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
gfx
/
show
/
mpeg_player122.lha
/
src
/
fs4.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-08
|
8KB
|
305 lines
/*
* Copyright (c) 1992 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/* This file contains C code to do YCrCb -> colormap space. */
#include "fs4.h"
#include "video.h"
#include "dither.h"
/* Structures containing precomputed error terms. */
static FS4Dither lum_index[256];
static FS4Dither cr_index[256];
static FS4Dither cb_index[256];
/*
*--------------------------------------------------------------
*
* InitFS4Dither --
*
* Initializes structures used for f-s dithering. Precomputes
* error terms.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
InitFS4Dither()
{
int i;
for (i=0; i<256; i++) {
lum_index[i].value = (i * LUM_RANGE) / 256;
lum_index[i].e1 = (7 * (i-lum_values[lum_index[i].value])) / 16;
lum_index[i].e2 = (i-lum_values[lum_index[i].value])/16;
lum_index[i].e3 = (5 * (i - lum_values[lum_index[i].value])) / 16;
lum_index[i].e4 = (i-lum_values[lum_index[i].value]) - lum_index[i].e1 -
lum_index[i].e2 - lum_index[i].e3;
lum_index[i].value *= LUM_BASE;
cr_index[i].value = (i * CR_RANGE) / 256;
cr_index[i].e1 = (7 * (i-cr_values[cr_index[i].value])) / 16;
cr_index[i].e2 = (i-cr_values[cr_index[i].value])/16;
cr_index[i].e3 = (5 * (i - cr_values[cr_index[i].value])) / 16;
cr_index[i].e4 = (i-cr_values[cr_index[i].value]) - cr_index[i].e1 -
cr_index[i].e2 - cr_index[i].e3;
cr_index[i].value *= CR_BASE;
cb_index[i].value = (i * CB_RANGE) / 256;
cb_index[i].e1 = (7 * (i-cb_values[cb_index[i].value])) / 16;
cb_index[i].e2 = (i-cb_values[cb_index[i].value])/16;
cb_index[i].e3 = (5 * (i - cb_values[cb_index[i].value])) / 16;
cb_index[i].e4 = (i-cb_values[cb_index[i].value]) - cb_index[i].e1 -
cb_index[i].e2 - cb_index[i].e3;
cb_index[i].value *= CB_BASE;
}
}
/*
*--------------------------------------------------------------
*
* DitherImage --
*
* Converts lum, cr, cb image planes into fixed colormap
* space. Uses Floyd-Steinberg dithering in serpentine
* pattern with standard 4 errors propogated.
*
* Results:
* The display plane is replaced by 8-bit colormap space
* image.
*
* Side effects:
* Hopefully, none.
*
*--------------------------------------------------------------
*/
void
FS4DitherImage(lum, cr, cb, disp, rows, cols)
unsigned char *lum, *cr, *cb, *disp;
int rows, cols;
{
static char *cur_row_error, *next_row_error;
static int first = 1;
char *cur_row_err_mark, *next_row_err_mark;
char *temp;
int i, j, pixsum, c_cols;
unsigned char *cur_row, *channel, *dest_row;
FS4Dither *chan_index;
if (first) {
cur_row_error = (char *) malloc(cols+2);
next_row_error = (char *) malloc(cols+2);
first = 0;
}
memset(cur_row_error, 0, cols+2);
memset(next_row_error, 0, cols+2);
for(i=0; i<rows; i+=2) {
cur_row = lum + (i*cols);
dest_row = disp + (i*cols);
cur_row_err_mark = cur_row_error + 1;
next_row_err_mark = next_row_error + 1;
for (j=0; j<cols; j++) {
pixsum = *cur_row + *cur_row_err_mark;
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
*dest_row = lum_index[pixsum].value;
*(cur_row_err_mark+1) += lum_index[pixsum].e1;
*(next_row_err_mark+1) += lum_index[pixsum].e2;
*next_row_err_mark += lum_index[pixsum].e3;
*(next_row_err_mark-1) += lum_index[pixsum].e4;
cur_row++;
dest_row++;
cur_row_err_mark++;
next_row_err_mark++;
}
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
memset(next_row_error, 0, cols+2);
cur_row += cols-1;
dest_row += cols-1;
cur_row_err_mark = cur_row_error + cols;
next_row_err_mark = next_row_error + cols;
for (j=0; j<cols; j++) {
pixsum = *cur_row + *cur_row_err_mark;
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
*dest_row = lum_index[pixsum].value;
*(cur_row_err_mark-1) += lum_index[pixsum].e1;
*(next_row_err_mark-1) += lum_index[pixsum].e2;
*next_row_err_mark += lum_index[pixsum].e3;
*(next_row_err_mark+1) += lum_index[pixsum].e4;
cur_row--;
dest_row--;
cur_row_err_mark--;
next_row_err_mark--;
}
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
memset(next_row_error, 0, cols+2);
}
memset(cur_row_error, 0, cols+2);
c_cols = cols >> 1;
channel = cr;
chan_index = cr_index;
repeat:
for (i=0; i < rows; i+=2) {
cur_row = channel + ((i>>1)*c_cols);
dest_row = disp + (i*cols);
cur_row_err_mark = cur_row_error+1;
next_row_err_mark = next_row_error+1;
for (j=0; j<cols; j++) {
int p_val;
p_val = *cur_row;
pixsum = *cur_row_err_mark + p_val;
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
*dest_row += chan_index[pixsum].value;
*(cur_row_err_mark+1) += chan_index[pixsum].e1;
*(next_row_err_mark+1) += chan_index[pixsum].e2;
*next_row_err_mark += chan_index[pixsum].e3;
*(next_row_err_mark-1) += chan_index[pixsum].e4;
if (j&1) cur_row++;
dest_row++;
cur_row_err_mark++;
next_row_err_mark++;
}
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
memset(next_row_error, 0, cols+2);
cur_row += c_cols-1;
dest_row += cols-1;
cur_row_err_mark = cur_row_error+cols;
next_row_err_mark = next_row_error+cols;
for (j=0; j<cols; j++) {
int p_val;
p_val = *cur_row;
pixsum = *cur_row_err_mark + p_val;
if (pixsum < 0) pixsum = 0;
else if (pixsum > 255) pixsum = 255;
*dest_row += chan_index[pixsum].value;
*(cur_row_err_mark-1) += chan_index[pixsum].e1;
*(next_row_err_mark-1) += chan_index[pixsum].e2;
*next_row_err_mark += chan_index[pixsum].e3;
*(next_row_err_mark+1) += chan_index[pixsum].e4;
if (j&1) cur_row--;
dest_row--;
cur_row_err_mark--;
next_row_err_mark--;
}
temp = cur_row_error;
cur_row_error = next_row_error;
next_row_error = temp;
memset(next_row_error, 0, cols+2);
}
if (channel == cr) {
channel = cb;
chan_index = cb_index;
memset(cur_row_error, 0, cols+2);
goto repeat;
}
dest_row = disp;
for (i=0; i<rows; i++) {
for (j=0; j<cols; j++) {
*dest_row = pixel[*dest_row];
dest_row++;
}
}
}